#include "itemfactorymodel.h"

#include "other/rosterelements.h"

#include <QDebug>

ItemFactoryModelItem::ItemFactoryModelItem(const QString& _key, yALB_AbstractTreeItem *parent) :
    key(_key), yALB_AbstractTreeItem(parent)
{
}

ItemFactoryModelItem* ItemFactoryModelItem::parent() const {
    return dynamic_cast<ItemFactoryModelItem*>(yALB_AbstractTreeItem::parent());
}

ItemFactoryModelItem* ItemFactoryModelItem::child(int i) const {
    return static_cast<ItemFactoryModelItem*>(yALB_AbstractTreeItem::child(i));
}

ItemFactoryModel::ItemFactoryModel(const DualCollection<GameItem> *items,
                                   const DualCollection<GameCategory> *categories,
                                   QObject *parent) :
    yALB_AbstractTreeModel(new yALB_AbstractTreeItem(NULL), parent),
    _items(items), _categories(categories)
{
    Q_ASSERT(items && categories);
}

ItemFactoryModel::~ItemFactoryModel() {
    delete rootItem;
}

QVariant ItemFactoryModel::data(const QModelIndex &index, int role) const {
    if(!index.isValid())
        return QVariant();

    ItemFactoryModelItem *item = static_cast<ItemFactoryModelItem*>(index.internalPointer());

    if(role == Qt::UserRole)
        return item->key;

    if(role != Qt::DisplayRole)
        return QVariant();

    if(!item->parent()) { // Category
        if(index.column() != NameColumn)
            return QVariant();
        if(item->key.isEmpty())
            return tr("Unclassified");
        else
            return _categories->getRealElement(item->key)->getName();
    } else { // Item
        switch(index.column()) {
        case NameColumn:
            return _items->getRealElement(item->key)->getName();
        case CostColumn:
            return _items->getRealElement(item->key)->getCost();
        }
    }

    return QVariant();
}

QVariant ItemFactoryModel::headerData(int section, Qt::Orientation orientation,
                                      int role) const {
    if(orientation != Qt::Horizontal || role != Qt::DisplayRole)
        return QVariant();
    switch(section) {
    case NameColumn:
        return tr("Item name");
    case CostColumn:
        return tr("Cost");
    default:
        return QVariant();
    }
}

int ItemFactoryModel::columnCount(const QModelIndex &parent) const {
    Q_UNUSED(parent)
    return ColumnNumber;
}

void ItemFactoryModel::setSource(const RosterUnit *unit) {
    // Clear current list
    if(rootItem->childCount() > 0) {
        beginRemoveRows(QModelIndex(), 0, rootItem->childCount()-1);
        rootItem->clearChildren();
        endRemoveRows();
    }

    if(unit) {
        QHash<QString, int> categoryIndex;
        QSet<QString> addedCategories;
        QStringList keys(unit->getItemsWithAllowedInf());
        for(int i = 0; i<keys.size(); ++i) {
            const QString& key = keys.at(i);
            if(key.startsWith(QChar('>'))) { // A whole category
                const QString category(key.mid(1));

                if(addedCategories.contains(category))
                    continue;

                const QStringList itemsInCategory(categoryItems.value(category));
                if(itemsInCategory.size() == 0)
                    continue;

                int rowNumber = rootItem->childCount();
                beginInsertRows(QModelIndex(), rowNumber, rowNumber);
                ItemFactoryModelItem *categoryRow = new ItemFactoryModelItem(category, rootItem);
                for(int j = 0; j<itemsInCategory.size(); ++j) {
                    if(unit->isAllowedItem(itemsInCategory.at(j), false))
                        new ItemFactoryModelItem(itemsInCategory.at(j), categoryRow);
                }
                addedCategories << category;
                endInsertRows();
            } else { // Single items
#ifdef EXTRA_CHECKS
                if(!_items->contains(key))
                    continue;
#endif
                GameItem *item = _items->getRealElement(key);
                if(!unit->isAllowedItem(key))
                    continue;

                int parentIndex;
#ifdef EXTRA_CHECKS
                QString category = _categories->contains(item->category) ? item->category : "";
#else
                QString category = item->category;
#endif
                if(addedCategories.contains(category))
                    continue;

                if(categoryIndex.contains(category)) {
                    parentIndex = categoryIndex.value(category);
                } else {
                    parentIndex = rootItem->childCount();
                    beginInsertRows(QModelIndex(), parentIndex, parentIndex);
                    new ItemFactoryModelItem(category, rootItem);
                    categoryIndex.insert(category, parentIndex);
                    endInsertRows();
                }

                ItemFactoryModelItem *parent = static_cast<ItemFactoryModelItem*>(rootItem->child(parentIndex));
                int row = parent->childCount();
                beginInsertRows(index(parent, 0), row, row);
                new ItemFactoryModelItem(key, parent);
                endInsertRows();
            }
        }

    }
}

void ItemFactoryModel::buildCategoryIndex() {
    categoryItems.clear();

    // Fill categoryItems with the item keys for each category

    QStringList keys(_items->keys());
    for(int i = 0; i<keys.size(); ++i) {
        categoryItems[_items->getRealElement(keys.at(i))->category] << keys.at(i);
    }
}

QString ItemFactoryModel::getItemKeyFromIndex(QModelIndex index) const {
    if(!index.isValid())
        return QString();
    ItemFactoryModelItem *item = static_cast<ItemFactoryModelItem*>(index.internalPointer());
    return item->key;
}
